﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mogre;

namespace WastedMechanics.NavMesh
{
    public class Polygon
    {
        public List<Vertex> Vertices;
        public List<Edge> Edges;
        public Mesh Mesh;
        public float Area;
        public Vector3 Center;
        Vertex LastVertex;
        Vertex FirstVertex;

        public float CurrentCost;
        public bool IsVisited;

        public Polygon(Mesh mesh)
        {
            Vertices = new List<Vertex>();
            Edges = new List<Edge>();
            Mesh = mesh;
        }

        public void BeginBuildingEdgeList()
        {
            LastVertex = null;
            FirstVertex = null;
        }

        public void EndBuildingEdgeList()
        {
            if (LastVertex != null)
            {
                Edge newEdge = Mesh.NewEdge(LastVertex, FirstVertex);
                newEdge.Polygons.Add(this);

                Edges.Add(newEdge);

                Center = Vector3.ZERO;
                Vertices.ForEach(vertex => Center += vertex.Position);
                Center /= (float)Vertices.Count;
                
                Area = 0;                
                Edges.ForEach(edge => Area += 0.5f * Mogre.Math.Abs((Helper.ProjXZ(edge.Begin.Position - Center)).CrossProduct(Helper.ProjXZ(edge.End.Position - Center))));
            }
        }
      
        public void AddEdgeListVertex(Vector3 pos)
        {
            Vertex newVertex = Mesh.NewVertex(pos);
            if (LastVertex != null)
            {
                Edge newEdge = Mesh.NewEdge(LastVertex, newVertex);
                newEdge.Polygons.Add(this);
                Edges.Add(newEdge);
            }
            if (FirstVertex == null)
                FirstVertex = newVertex;
            LastVertex = newVertex;

            Vertices.Add(newVertex);
        }

        public bool IsPointInside(Vector2 point)
        {
            if (Edges.Count != 0)
            {
                float area = 0;                
                Edges.ForEach(edge => 
                    area += 0.5f * Mogre.Math.Abs((Helper.ProjXZ(edge.Begin.Position) - point).CrossProduct(Helper.ProjXZ(edge.End.Position) - point))
                    );
                if (area > Area * 1.01f)
                    return false;
            }
            return true;
        }

        public float FindCost(Vector3 start, Vector3 goal)
        {
            return (start - Center).Length;
        }

        public void ResetData()
        {
            IsVisited = false;
            CurrentCost = 0;
        }
        
        public void Visualize()
        {
            if (Vertices.Count != 0)
            {
                ManualObject manOb = Engine.SceneManager.CreateManualObject();
                manOb.Begin("Debug/NavMeshRed", RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
                Edges.ForEach(edge =>
                {
                    manOb.Position(edge.Begin.Position + new Vector3(0, 0.1f, 0));
                    manOb.Position(edge.End.Position + new Vector3(0, 0.1f, 0));
                    manOb.Position(Center + new Vector3(0, 0.1f, 0));
                }); 
                manOb.End();

                SceneNode moNode = Engine.SceneManager.RootSceneNode.CreateChildSceneNode();
                moNode.Position = Vector3.ZERO;
                moNode.AttachObject(manOb);

                foreach (Vertex v in Vertices) v.Visualize();
            }
        }
    }
}
